﻿#region Imports
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization.Json;
using System.Web.Script.Serialization;
using System.Windows;
using CommonUtilities.Attributes;
using MyTraktDemo.Models;
#endregion Imports

namespace TraktApiWrapper.API
{
    /// <summary>
    /// https://trakt.tv/oauth/applications/6653
    /// </summary>
    public class APIStub
    {
        private const string baseUrl = @"https://trakt.tv";

        #region Service call and data processing
        public static string GenerateURL() { return ""; } // RKD

        public static string GenerateURL(eSearchModule module, string q)
        {
            string id_type = GetFriendlyName(module, String.Empty);
            id_type = String.IsNullOrEmpty(id_type) ? "" : "/" + id_type;

            string url = String.Format(@"https://trakt.tv/search{0}?utf8=%E2%9C%93&query={1}", id_type, FormatApiUrl(q).Replace(" ", "+"));
            return url; // RKD
        }

        private static string GetFriendlyName(object enumValue, string defDesc)
        {
            FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

            if (null != fi)
            {
                object[] attrs = fi.GetCustomAttributes(typeof(FriendlyNameAttribute), true);
                if (attrs != null && attrs.Length > 0)
                    return ((FriendlyNameAttribute)attrs[0]).FriendlyName;
            }

            return defDesc;
        }

        public static string GenerateURL(eModule module, MovieDBs ids, int indexSeason = -1, int indexEpisode = -1)
        {
            //string url = @"http://www.panoramio.com/map/get_panoramas.php?set=public&from=0&to=20&minx=-180&miny=-90&maxx=180&maxy=90&size=medium&mapfilter=true";
            //return url.FormatApiUrl();

            string url = baseUrl;
            switch (module)
            {
                case eModule.Movie:
                    url += String.Format(@"/movies/{0}", ids.slug);
                    break;

                case eModule.Show:
                case eModule.Season:
                case eModule.Episode:
                    url += String.Format(@"/shows/{0}", ids.slug);

                    if (module == eModule.Season || module == eModule.Episode)
                    {
                        if (indexSeason < 1) throw new InvalidOperationException("Inlvaid season index..");
                        url += String.Format(@"/seasons/{0}", indexSeason);
                    }

                    if (module == eModule.Episode)
                    {
                        if (indexEpisode < 1) throw new InvalidOperationException("Invalid episode index..");
                        url += String.Format(@"/episodes/{0}", indexEpisode);
                    }
                    break;

                case eModule.Person:
                    url += String.Format(@"/people/{0}", ids.slug);
                    break;

                //case eModule.Comment:
                //    url += String.Format(@"/comments/{0}", ids.id); 
                //    break;

                default:
                    throw new NotImplementedException("Unhandled module..");
            }

            return url;

            /* Type___  URL___________
             * movie    /movies/:slug
             * show     /shows/:slug
             * season   /shows/:slug/seasons/:num
             * episode  /shows/:slug/seasons/:num/episodes/:num
             * person   /people/:slug
             * comment  /comments/:id
             */

            // RKD
            //string baseURL = "http://www.panoramio.com/map/get_panoramas.php?set={8}&from={0}&to={1}&minx={2}&miny={4}&maxx={3}&maxy={5}&size={6}&mapfilter={7}";
            //return String.Format(baseURL, txtResultMin, txtResultMax, txtMinX, txtMaxX, txtMinY, txtMaxY, cmbSize, chkMapFilter, settype);
        }

        private static WebResponse CallService()
        {
            string url = GenerateURL();

            WebRequest request = WebRequest.Create(url);
            WebResponse ws = request.GetResponse();

            return ws;
        }

        public static TOutput FetchData_DataContractJsonSerializer<TOutput>()
            where TOutput : class, new()
        {
            try
            {
                WebResponse ws = CallService();
                DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(TOutput));
                TOutput output = (TOutput)jsonSerializer.ReadObject(ws.GetResponseStream());

                return output;
            }
            catch (WebException wex)
            {
                // exceptions from the server are communicated with a 4xx status code
                HandleWebException(wex);
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static TOutput FetchData_JavaScriptSerializer<TOutput>()
            where TOutput : class, new()
        {
            try
            {
                WebResponse ws = CallService();

                string jsonString = String.Empty;
                using (StreamReader sreader = new StreamReader(ws.GetResponseStream()))
                {
                    jsonString = sreader.ReadToEnd();
                }

                JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
                TOutput output = jsSerializer.Deserialize<TOutput>(jsonString);

                return output;
            }
            catch (WebException wex)
            {
                // exceptions from the server are communicated with a 4xx status code
                HandleWebException(wex);
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private static void HandleWebException(WebException wex)
        {
            string msg = "The server did not like your request.";

            HttpWebResponse hwr = wex.Response as HttpWebResponse;
            if (hwr != null)
            {
                msg += String.Format("\r\nThe status code is {0}, the status message: {1}.", (int)hwr.StatusCode, hwr.StatusDescription);
                using (StreamReader sreader = new StreamReader(hwr.GetResponseStream()))
                {
                    string errorMessage = sreader.ReadToEnd();
                    if (!String.IsNullOrEmpty(errorMessage))
                    {
                        msg += "\r\n\r\nThe further data sent from the server are:\r\n" + errorMessage;
                    }
                }
            }

            MessageBox.Show(msg, "Bad Request!");
        }
        #endregion Service call and data processing

        #region Supporting methods
        /// <summary>
        /// Formats API URL to replace special characters with corresponding HTML codes
        /// </summary>
        /// <param name="url">API URL to be formatted</param>
        /// <returns></returns>
        private static string FormatApiUrl(string url)
        {
            // %21@%23%24%25%5E%26*%28%29_%2B%3D-%7E%60%3A%3B%22%27%3C%2C%3E.%3F%2F
            // !@#$%^&*()_+=-~`:;"'<,>.?/

            return url //.Replace(" ", "%20")
                .Replace("\\", "%5C").Replace("#", "%23").Replace("+", "%2B");
        }
        #endregion Supporting methods

        #region TRY
        // http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
        /*
                #region Declarations
                #region Common
                /// <summary>
                /// All possible actions allowed for application with API/Services
                /// </summary>
                public enum ActionType
                {
                    /// <summary>
                    /// For Deleting data
                    /// </summary>
                    Delete,
                    /// <summary>
                    /// For Updating data
                    /// </summary>
                    Update,
                    /// <summary>
                    /// For Saving data
                    /// </summary>
                    Save,
                    /// <summary>
                    /// For Saving data with no confirmation dialog
                    /// </summary>
                    SaveNoDialog,
                    /// <summary>
                    /// For error logging
                    /// </summary>
                    Error,
                    /// <summary>
                    /// For fetching data after posting
                    /// </summary>
                    Get,
                    GetFile,
                    /// <summary>
                    /// For updating the Modifiers.
                    /// </summary>
                    UpdateModifiers,
                    /// <summary>
                    /// For Deleteing the Modifiers.
                    /// </summary>
                    DeleteModifiers,
                    /// <summary>
                    /// Others 
                    /// </summary>
                    Others
                }

                /// <summary>
                /// Action type declaration
                /// </summary>
                private ActionType eActionType;

                /// <summary>
                /// JSON string before and after API post operation in case of excel upload and download
                /// </summary>
                string stringJSON = "";

                private const string DEFAULT_HTTPREQUEST_CONTENTTYPE = "application/json";
                private const string HEADERNAME_XAUTHKEY = "X-AuthKey";
                #endregion

                #region APIGet
                /// <summary>
                /// defines an event delegate for Get
                /// </summary>
                /// <param name="sender">Sender</param>
                /// <param name="e">Custom event argument</param>
                public delegate void GetServiceCustomEventHandler(object sender, TraktEventArgs<object> e);
                /// <summary>
                /// defined event implementation for Get
                /// </summary>
                public event GetServiceCustomEventHandler GetServiceEvent;
                #endregion
                #endregion

                #region API GET Methods
                /// <summary>
                /// Triggers Get Response to fetch data
                /// </summary>
                /// <typeparam name="T">Type of item in the collection</typeparam>
                /// <param name="_APIAppenededUrl">URL to be appended with Service IP</param>
                /// <param name="GenericListColl"></param>
                public void APIGet<T>()
                {
                    var url = GenerateURL(eModule.Show, new MovieDBs { slug = "the-flash-2014" });
                    Uri uri = new Uri(url, UriKind.Absolute);

                    bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
                    bool httpResultSecured = WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                    request.Headers["content-type"] = DEFAULT_HTTPREQUEST_CONTENTTYPE;
                    request.Method = "GET"; // ResourceUtilities.RequestMethod_Get;
                    request.BeginGetResponse((new AsyncCallback(OnGetRequestStreamCompleted)), request);
                }

                /// <summary>
                /// Recieves data via Async Callback
                /// </summary>
                /// <param name="ar">Represents the status of an asynchronous operation</param>
                public void OnGetRequestStreamCompleted(IAsyncResult ar)
                {
                    HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
                    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(ar);

                    Stream responseStream = response.GetResponseStream();
                    JsonArray _jsonResponse = (JsonArray)JsonArray.Load((Stream)responseStream);

                    / ******************Passing stream Response back to calling method***************************** /
                    if (GetServiceEvent != null) GetJsonResponse(_GenericObject, new TraktEventArgs<object>(_jsonResponse));
                    / ******************Passing stream Response back to calling method***************************** /
                }

                /// <summary>
                /// Gets JSon response after completion of request
                /// </summary>
                /// <param name="sender">Sender</param>
                /// <param name="e">Custom event argument</param>
                private void GetJsonResponse(object sender, TraktEventArgs<object> e)
                {
                    if (GetServiceEvent != null) GetServiceEvent(sender, e);
                }
                #endregion
                */
        #endregion TRY
    }
}
